import com.bit.demo1.Test;

//这里我们探讨继承
class Animal{
    public String name;
    public int age;
    private int count;//父类中的私有方法不能访问
    protected int p;

    public void eat(){
        System.out.println(name + "ani::eat");
    }

    public Animal(String name, int age){
        eat();
        this.name = name;
        this.age = age;
    }
}

class Dog extends Animal{
    //子类构造的同时，要帮助父类来进行构造
    public Dog(String name, int age){
        super(name, age);//实现父类带有两个参数的构造方法
    }

    @Override
    public void eat(){
        System.out.println(name + "狼吞虎咽");
    }
    //重写注意事项：
    //1、private、static、final方法不能重写
    //2、子类的访问限定符要大于等于父类的限定符
    //3、一个类里面不能重写
}

class Bird extends Animal{
    public String wing;
    public String name = "jj";//重名变量

    public void fly(){
        System.out.println(name + "fly");
        //与"System.out.println(super.name + "fly");"不同
    }

    public Bird(String name, int age, String wing){
        super(name, age);//实现父类带有两个参数的构造方法
        this.wing = wing;
    }
}

//讲一下protetced，即访问其他包父类的变量
class Test2 extends Test {//继承了别的包的类
    public static void main3(String[] args) {
        Test2 test2 = new Test2();
        //System.out.println(test2.val);错误
        System.out.println(test2.count);//但是protected就可以
    }
}

public class inheritTest {

    public static void main(String[] args) {
        //这里dog实例化，会先调用父类的构造方法
        //父类的构造方法内有eat方法
        //所以这里的eat会用哪个呢？结果是子类的，这里也发生了动态绑定
        Dog dog = new Dog("haha", 20);
    }

    public static void main5(String[] args) {
        //向下转型
        Animal animal = new Bird("haha", 20, "我要飞的更高");
        Bird bird = (Bird) animal;
        //不是所有动物都会飞，要判断
        if (bird instanceof Bird){
            bird.fly();
        }
    }

    public static void func(Animal animal) {

    }
    public static Animal func2(){
        Dog dog = new Dog("hehe",20);
        return dog;
    }
    public static void main4(String[] args) {
        //向上转型，即父类引用 引用子类对象
        Animal animal = new Dog("haha", 19);
        //第二种情况，用函数
        Dog dog = new Dog("hehe",20);
        func(dog);
        //第三种情况，返回值
        func2();

        //动态绑定条件：（运行时绑定）
        //重载时找对应方法就是静态绑定（编译时多态）
        //父类引用引用子类对象（向上转型）
        //父类引用子类重写的方法
        animal.eat();

        //animal的类型毕竟是Animal类型，父类引用只能访问自己父类成员
        Animal animal1 = new Bird("heihei", 20, "我要飞的更高");
        System.out.println(animal1.name);//这里访问了父类的name
        //animal1.wing;错误
    }

    public static void main2(String[] args) {
        Bird bird = new Bird("hh", 18, "fly");
        //这里父类初始化了，但是子类没有。在子类和父类同名变量时，子类中的变量优先，除非使用super
        bird.fly();
    }

    public static void main1(String[] args) {
        Dog dog = new Dog("hh", 18);
        dog.name = "hh";
        System.out.println(dog.name);
        dog.eat();


        Bird bird = new Bird("ll", 20, "fly");
        bird.eat();
        bird.fly();
    }
}

//作业：
//1、重载与重写区别
//2、this与super区别